package dev.ece.core.vertex;

import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.Iterator;
import java.util.List;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;

import dev.ece.core.clearup.ClearUpGLRubbish;
import dev.ece.core.clearup.ClearUpGLRubbishManager;
import dev.ece.util.tools.BufferBuilder;

public class EBO implements ClearUpGLRubbish {

	private int eboBufferHandler;
	
	private int count;
	
	private int type;
	
	public EBO() {
		this.eboBufferHandler = GL15.glGenBuffers();
	}
	
	public void bind() {
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, this.getEboBufferHandler());
	}
	
	public int getEboBufferHandler() {
		return eboBufferHandler;
	}

	public int getCount() {
		return count;
	}

	public int getType() {
		return type;
	}

	public void finish() {
		unbind();
	}
	
	public static EBO newInstance(short[] indice) {
		EBO ebo = new EBO();
		ebo.count = indice.length;
		ebo.type = GL11.GL_UNSIGNED_SHORT;
		ShortBuffer buffer = BufferBuilder.buildShortBuffer(ebo.count * 2);
		buffer.put(indice);
		buffer.rewind();
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo.getEboBufferHandler());
		GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
		return ebo;
	}
	
	public static EBO newInstanceShort(List<Short> indice) {
		EBO ebo = new EBO();
		ebo.count = indice.size();
		ebo.type = GL11.GL_UNSIGNED_SHORT;
		ShortBuffer buffer = BufferBuilder.buildShortBuffer(indice.size() * 2);
		Iterator<Short> it = indice.iterator();
		while(it.hasNext()) {
			buffer.put(it.next());
		}
		buffer.rewind();
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo.getEboBufferHandler());
		GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
		return ebo;
	}
	
	public static EBO newInstance(int[] indice) {
		EBO ebo = new EBO();
		ebo.count = indice.length;
		ebo.type = GL11.GL_UNSIGNED_INT;
		IntBuffer buffer = BufferBuilder.buildIntBuffer(ebo.count * 4);
		buffer.put(indice);
		buffer.rewind();
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo.getEboBufferHandler());
		GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
		return ebo;
	}
	
	public static EBO newInstanceInt(List<Integer> indice) {
		EBO ebo = new EBO();
		ebo.count = indice.size();
		ebo.type = GL11.GL_UNSIGNED_INT;
		IntBuffer buffer = BufferBuilder.buildIntBuffer(ebo.count * 4);
		Iterator<Integer> it = indice.iterator();
		while(it.hasNext()) {
			buffer.put(it.next());
		}
		buffer.rewind();
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo.getEboBufferHandler());
		GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
		return ebo;
	}
	
	/**
	 * @param mode
	 */
	public void glDrawElements(int mode) {
		GL11.glDrawElements(mode, count, type, 0);
	}
	
	public static void unbind() {
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
	}

	public void destroy() {
		ClearUpGLRubbishManager.push(this);
	}
	
	@Override
	public void clearup() {
		GL15.glDeleteBuffers(this.getEboBufferHandler());
	}
	
}
